<?php

namespace app\admin\service;

use app\admin\model\order\Mobile;
use app\api\service\CommonService;
use app\common\model\Alipay;
use app\model\Agent;
use app\model\AgentBalanceLog;
use app\model\AgentRefund as Model;
use app\model\AgentRefundConfig;
use app\model\PayLog;
use think\facade\Db;

class AgentRefund extends CommonService
{
    /**
     * 同意退款申请
     */
    public function accept($id)
    {
        $model = Model::where('state', 1)->find($id);
        if (!$model) {
            return $this->inValiReturn('数据不存在');
        }

        $agent = Agent::find($model['agent_id']);

        Db::startTrans();
        try {
            $model->state = 2;
            $model->save();

            // 没啥用
            $res = AgentBalanceLog::where('flow_step', 1)
                ->where('agent_id', $model['agent_id'])
                ->where('type', BALANCE_REFUND_APPLY)
                ->where('quote_id', $model->id)
                ->update(['flow_step' => 9]);
            if (!$res) {
                Db::rollback();

                return $this->inValiReturn('操作失败');
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            doLog(getExceptionMsg($e));

            return $this->inValiReturn('退款审核失败，请重试或者联系我们');
        }

        // 操作退款，返回值不做判断
        // $this->doRefund($model);

        return $this->valiReturn();
    }

    /**
     * 拒绝退款申请
     */
    public function reject($param)
    {
        $model = Model::where('state', 1)->find($param['id']);
        if (!$model) {
            return $this->inValiReturn('数据不存在');
        }

        $agent = Agent::find($model['agent_id']);

        Db::startTrans();
        try {
            $model->state = 3;
            $model->remark = $param['remark'];

            if (!$model->save()) {
                Db::rollback();

                return $this->inValiReturn('操作失败1');
            }

            $res = Agent::where('id', $model['agent_id'])
                ->inc('balance', $model['amount'])
                ->inc('recharge_amount', $model['amount'])
                ->update([
                    'balance_last_updated_at' => date('Y-m-d H:i:s'),
                ]);
            if (!$res) {
                Db::rollback();

                return $this->inValiReturn('操作失败2');
            }

            // 具体后，对应balance_log标记为流程已完成
            $res = AgentBalanceLog::where('flow_step', 1)
                ->where('agent_id', $model['agent_id'])
                ->where('type', BALANCE_REFUND_APPLY)
                ->where('quote_id', $model->id)
                ->update([
                    'flow_step' => 9
                ]);
            if (!$res) {
                Db::rollback();

                return $this->inValiReturn('操作失败3');
            }

            $newBalanceLog = [
                'agent_id' => $model['agent_id'],
                'type' => BALANCE_REFUND_REJECT,
                'amount' => $model['amount'],
                'old_balance' => $agent['balance'],
                'new_balance' => $agent['balance'] + $model['amount'],
                'remark' => '拒绝退款申请 ' . fen2yuan($model['amount']) . ' 元',
                'quote_id' => $model['id'],
            ];
            (new AgentBalanceLog())->save($newBalanceLog);
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            return $this->inValiReturn($e->getMessage());
        }

        return $this->valiReturn();
    }

    /*
     获取待退款的订单信息(可以申请退款的订单信息)
    */
    public function getOrderInfo($agentId, $orderSn)
    {
        return PayLog::alias('paylog')->hasWhere('balanceLog', function ($query) {
            $query->where('flow_step', 1);
        })->where('paylog.agent_id', $agentId)
            ->where('order_id', $orderSn)
            ->where('paylog.status', 2)->find();
    }

    /*
     退款申请
     data [mobile,alipay,wechat,order_sn]
    */
    public function apply($agentId, $data)
    {
        // 退款配置检验
        $refundConfig = AgentRefundConfig::where('agent_id', 0)->find();
        if ($refundConfig) {
            // 最后一笔充值完成xx天后，才能退款
            $recharge = Db::name('agent_balance_log')
                ->field('created_at')
                ->where('agent_id', $agentId)
                ->where('type', 'in', [6, 8])
                ->order('id desc')
                ->find();
            $day = 0;
            if ($recharge) {
                $time = time() - strtotime($recharge['created_at']);
                $day = floor($time / 86400);
            }
            if ($day < $refundConfig->interval_day) {
                return $this->inValiReturn('最后一笔充值完成 ' . $refundConfig->interval_day . ' 天后，才能再次发起退款');
            }

            $autoApproveMax = yuan2fen($refundConfig->auto_aprove_max);
        } else {
            $autoApproveMax = -1;
        }

        if ($refundConfig && $data['amount'] <= $autoApproveMax) {
            $state = 2;
            $remark = '申请退款且自动通过审核';
        } else {
            $state = 1;
            $remark = '申请退款';
        }

        // 进入退款审核提交流程
        $refundData = [
            'agent_id' => $agentId,
            'refund_rate' => $refundConfig ? $refundConfig->rate : 0,
            'state' => $state,
        ];
        $refundData = array_merge($refundData, $data);

        $agentInfo = Agent::find($agentId);
        if ($agentInfo['balance'] < $data['amount']) {
            return $this->inValiReturn('账户余额不足');
        }

        Db::startTrans();
        try {
            $res = Db::name('agent')
                ->where('id', $agentId)
                ->where('balance', '>=', $data['amount'])
                ->dec('balance', $data['amount'])
                ->dec('recharge_amount', $data['amount'])
                ->update([
                    'balance_last_updated_at' => date('Y-m-d H:i:s'),
                ]);
            if (!$res) {
                Db::rollback();
                return $this->inValiReturn('账户余额不足。' . __LINE__);
            }

            $id = Db::name('agent_refund')
                ->insertGetId($refundData);

            Db::name('agent_balance_log')
                ->insert([
                    'agent_id' => $agentId,
                    'type' => BALANCE_REFUND_APPLY,
                    'amount' => -$data['amount'],
                    'old_balance' => $agentInfo->balance,
                    'new_balance' => $agentInfo->balance - $data['amount'],
                    'remark' => $remark . ' ' . fen2yuan($data['amount']) . ' 元',
                    'quote_id' => $id,
                ]);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            doLog(getExceptionMsg($e));
            return $this->inValiReturn('退款申请失败：' . $e->getMessage());
        }

        return $this->valiReturn();
    }

    /*
     退款撤销
    */
    public function cancelByBalanceLogId($agentId, $balanceLogId)
    {
        $balanceLog = AgentBalanceLog::where('agent_id', $agentId)->where('type', BALANCE_REFUND_APPLY)->where('flow_step', 1)->find($balanceLogId);
        if (!$balanceLog) {
            return $this->inValiReturn('没有可以取消审核的数据，请刷新页面查看或者联系我们'.__LINE__);
        }
        $model = Model::where('agent_id', $agentId)->where('state', 1)->find($balanceLog->quote_id);
        if (!$model) {
            return $this->inValiReturn('没有可以取消审核的数据，请刷新页面查看或者联系我们' . __LINE__);
        }

        $agentInfo = Agent::find($agentId);

        Db::startTrans();
        try {
            $res = $model->where('state', 1)->save(['state' => 4]);
            if (!$res) {
                Db::rollback();

                return $this->inValiReturn('没有可以取消审核的数据，请刷新页面查看或者联系我们' . __LINE__);
            }

            $res = Agent::where('id', $agentId)
                ->inc('balance', $model->amount)
                ->inc('recharge_amount', $model->amount)
                ->update([
                    'balance_last_updated_at' => date('Y-m-d H:i:s'),
                ]);
            if (!$res) {
                Db::rollback();

                return $this->inValiReturn('撤销失败，请重试或者联系我们');
            }

            // 更新流程状态
            $res = AgentBalanceLog::where('id', $balanceLogId)->where('type', BALANCE_REFUND_APPLY)->where('flow_step', 1)->update(['flow_step' => 9]);
            if (!$res) {
                Db::rollback();

                return $this->inValiReturn('撤销失败，请重试或者联系我们');
            }
            $newBalanceLog = [
                'agent_id' => $agentId,
                'type' => BALANCE_REFUND_CANCEL,
                'amount' => $model->amount,
                'old_balance' => $agentInfo->balance,
                'new_balance' => $agentInfo->balance + $model->amount,
                'remark' => '撤销退款申请' . fen2yuan($model->amount) . ' 元',
                'quote_id' => $model->id,
            ];
            $res = (new AgentBalanceLog())->save($newBalanceLog);
            if (!$res) {
                Db::rollback();

                return $this->inValiReturn('撤销失败，请重试或者联系我们');
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            doLog(getExceptionMsg($e));

            return $this->inValiReturn('撤销失败，请重试或者联系我们');
        }

        return $this->valiReturn();
    }

    /*
     * 退款操作
     *
     * toto 未完成，待完成
     */
    public function doRefund($model)
    {
        $cacheKey = 'refund_' . $model->id;
        if (cache($cacheKey)) {
            return $this->valiReturn('已经退款成功，数据尚未更正，请联系我们');
        }
        $transerRes = 0;
        try {
            $data = [
                'out_biz_no' => $model->id,
                'trans_amount' => fen2yuan($model->amount - $model->amount * $model->refund_rate / 100),  // 实际为扣除手续费后的金额
                'product_code' => 'TRANS_ACCOUNT_NO_PWD',
                'biz_scene' => 'DIRECT_TRANSFER',
                'order_title' => '退款',
                'payee_info' => [
                    'identity' => $model->alipay,  // 参与方的唯一标识
                    'identity_type' => 'ALIPAY_LOGON_ID', // 1、ALIPAY_USER_ID 支付宝的会员ID  2、ALIPAY_LOGON_ID：支付宝登录号，支持邮箱和手机号格式
                ],
            ];

            $transerRes = Alipay::make(0)->transfer($data);
        } catch (\Exception $e) {
            doLog(getExceptionMsg($e));
        }

        if ($transerRes) { //退款成功
            $refundState = 5;
            $remark = '退款成功';
        } else {
            $refundState = 6;
            $remark = '退款失败';
        }

        $model->state = $refundState;
        Db::startTrans();
        try {
            $model->save();
        } catch (\Exception $e) {
            doWarning($remark . getExceptionMsg($e));
            if ($transerRes) {
                // todo 做警报
                cache($cacheKey, 1, 86400); //已经退款成功但是数据库操作失败的，加个锁定

                return $this->valiReturn();
            }

            return $this->inValiReturn('退款失败，请重试或者联系我们');
        }
    }
}
